home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsio / fsioFile.c < prev    next >
C/C++ Source or Header  |  1991-04-01  |  54KB  |  1,757 lines

  1. /* 
  2.  * fsioFile.c --
  3.  *
  4.  *    Routines for operations on files.  A file handle is identified
  5.  *    by using the <major> field of the Fs_FileID for the domain index,
  6.  *    and the <minor> field for the file number.
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /sprite/src/kernel/fsio/RCS/fsioFile.c,v 9.38 91/03/30 17:09:39 mgbaker Exp Locker: mgbaker $ SPRITE (Berkeley)";
  21. #endif not lint
  22.  
  23.  
  24. #include <sprite.h>
  25. #include <fs.h>
  26. #include <fsutil.h>
  27. #include <fsconsist.h>
  28. #include <fsio.h>
  29. #include <fsioFile.h>
  30. #include <fslcl.h>
  31. #include <fsNameOps.h>
  32. #include <fscache.h>
  33. #include <fsprefix.h>
  34. #include <fsioLock.h>
  35. #include <fsdm.h>
  36. #include <fsrmt.h>
  37. #include <fsStat.h>
  38. #include <vm.h>
  39. #include <rpc.h>
  40. #include <recov.h>
  41.  
  42. #ifdef SOSP91
  43. #include <sospRecord.h>
  44. #endif
  45.  
  46. #include <stdio.h>
  47. void IncVersionNumber _ARGS_((Fsio_FileIOHandle    *handlePtr));
  48.  
  49. /*
  50.  *----------------------------------------------------------------------
  51.  *
  52.  * Fsio_LocalFileHandleInit --
  53.  *
  54.  *    Initialize a handle for a local file from its descriptor on disk.
  55.  *
  56.  * Results:
  57.  *    An error code from the read of the file descriptor off disk.
  58.  *
  59.  * Side effects:
  60.  *    Create and install a handle for the file.  It is returned locked
  61.  *    and with its reference count incremented if SUCCESS is returned.
  62.  *
  63.  *----------------------------------------------------------------------
  64.  */
  65. ReturnStatus
  66. Fsio_LocalFileHandleInit(fileIDPtr, name, descPtr, cantBlock, newHandlePtrPtr)
  67.     Fs_FileID    *fileIDPtr;
  68.     char    *name;
  69.     Fsdm_FileDescriptor *descPtr;
  70.     Boolean    cantBlock;
  71.     Fsio_FileIOHandle    **newHandlePtrPtr;
  72. {
  73.     register ReturnStatus status;
  74.     register Fsio_FileIOHandle *handlePtr;
  75.     register Fsdm_Domain *domainPtr;
  76.     register Boolean found;
  77.     Boolean allocated = FALSE;
  78.  
  79.     found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fsio_FileIOHandle), name,
  80.             cantBlock, (Fs_HandleHeader **)newHandlePtrPtr);
  81.     if (found) {
  82.     if ((*newHandlePtrPtr) == (Fsio_FileIOHandle *) NIL) {
  83.         return FS_WOULD_BLOCK;
  84.     }
  85.     /*
  86.      * All set.
  87.      */
  88.     if ((*newHandlePtrPtr)->descPtr == (Fsdm_FileDescriptor *)NIL) {
  89.         panic("Fsio_LocalFileHandleInit, found handle with no descPtr\n");
  90.     }
  91.     return(SUCCESS);
  92.     }
  93.     status = SUCCESS;
  94.     handlePtr = *newHandlePtrPtr;
  95.     domainPtr = Fsdm_DomainFetch(fileIDPtr->major, FALSE);
  96.     if (domainPtr == (Fsdm_Domain *)NIL) {
  97.     Fsutil_HandleRelease(handlePtr, FALSE);
  98.     Fsutil_HandleRemove(handlePtr);
  99.     return(FS_DOMAIN_UNAVAILABLE);
  100.     }
  101.     if (descPtr == (Fsdm_FileDescriptor *) NIL) { 
  102.     /*
  103.      * Get a hold of the disk file descriptor.
  104.      */
  105.     allocated = TRUE;
  106.     descPtr = (Fsdm_FileDescriptor *)malloc(sizeof(Fsdm_FileDescriptor));
  107.     status = Fsdm_FileDescFetch(domainPtr, fileIDPtr->minor, descPtr);
  108.     if (status == FS_FILE_NOT_FOUND) {
  109.         status = FS_FILE_REMOVED;
  110.     }
  111.     if ((status != SUCCESS) && (status != FS_FILE_REMOVED)) {
  112.         printf( 
  113.         "Fsio_LocalFileHandleInit: Fsdm_FileDescFetch of %d failed 0x%x\n",
  114.                 fileIDPtr->minor, status);
  115.     }
  116.     } 
  117.     if ((status == SUCCESS) && !(descPtr->flags & FSDM_FD_ALLOC)) {
  118.     status = FS_FILE_REMOVED;
  119.     }
  120.     if (status == SUCCESS) { 
  121.     Fscache_Attributes attr;
  122.  
  123.     handlePtr->descPtr = descPtr;
  124.     handlePtr->flags = 0;
  125.     /*
  126.      * The use counts are updated when an I/O stream is opened on the file
  127.      */
  128.     handlePtr->use.ref = 0;
  129.     handlePtr->use.write = 0;
  130.     handlePtr->use.exec = 0;
  131.  
  132.     /*
  133.      * Copy attributes that are cached in the handle.
  134.      */
  135.     attr.firstByte = descPtr->firstByte;
  136.     attr.lastByte = descPtr->lastByte;
  137.     attr.accessTime = descPtr->accessTime;
  138.     attr.createTime = descPtr->createTime;
  139.     attr.modifyTime = descPtr->dataModifyTime;
  140.     attr.userType = descPtr->userType;
  141.     attr.permissions = descPtr->permissions;
  142.     attr.uid = descPtr->uid;
  143.     attr.gid = descPtr->gid;
  144.  
  145.     Fscache_FileInfoInit(&handlePtr->cacheInfo, 
  146.         (Fs_HandleHeader *)handlePtr,
  147.         descPtr->version, TRUE, &attr, domainPtr->backendPtr);
  148.  
  149.     Fsconsist_Init(&handlePtr->consist, (Fs_HandleHeader *)handlePtr);
  150.     Fsio_LockInit(&handlePtr->lock);
  151.     Fscache_ReadAheadInit(&handlePtr->readAhead);
  152.  
  153.     handlePtr->segPtr = (Vm_Segment *)NIL;
  154.     }
  155.     if (status != SUCCESS) {
  156.     Fsutil_HandleRelease(handlePtr, FALSE);
  157.     Fsutil_HandleRemove(handlePtr);
  158.     if (allocated) {
  159.         free((Address)descPtr);
  160.      }
  161.     *newHandlePtrPtr = (Fsio_FileIOHandle *)NIL;
  162.     } else {
  163.     if (descPtr->fileType == FS_DIRECTORY) {
  164.         fs_Stats.object.directory++;
  165.     } else {
  166.         fs_Stats.object.files++;
  167.     }
  168.     *newHandlePtrPtr = handlePtr;
  169.     }
  170.     Fsdm_DomainRelease(fileIDPtr->major);
  171.     return(status);
  172. }
  173.  
  174. /*
  175.  *----------------------------------------------------------------------
  176.  *
  177.  * Fsio_FileSyncLockCleanup --
  178.  *
  179.  *    This takes care of the dynamically allocated Sync_Lock's that
  180.  *    are embedded in a Fsio_FileIOHandle.  This routine is
  181.  *    called when the file handle is being removed.
  182.  *
  183.  * Results:
  184.  *    None.
  185.  *
  186.  * Side effects:
  187.  *    The locking statistics for this handle are combined with the
  188.  *    summary statistics for the lock types in the handle
  189.  *
  190.  *----------------------------------------------------------------------
  191.  */
  192. void
  193. Fsio_FileSyncLockCleanup(handlePtr)
  194.     Fsio_FileIOHandle *handlePtr;
  195. {
  196.     Fsconsist_SyncLockCleanup(&handlePtr->consist);
  197.     Fscache_InfoSyncLockCleanup(&handlePtr->cacheInfo);
  198.     Fscache_ReadAheadSyncLockCleanup(&handlePtr->readAhead);
  199. }
  200.  
  201. /*
  202.  *----------------------------------------------------------------------
  203.  *
  204.  * Fsio_FileNameOpen --
  205.  *
  206.  *    This is called in two cases after name lookup on the server.
  207.  *    The first is when a client is opening the file from Fs_Open.
  208.  *    The second is when a lookup is done when getting/setting the
  209.  *    attributes of the files.  In the open case this routine has
  210.  *    to set up Fsio_FileState that the client will use to complete
  211.  *    the setup of its stream, and create a server-side stream.
  212.  *    The handle should be locked upon entry, it remains locked upon return.
  213.  *
  214.  * Results:
  215.  *    SUCCESS.
  216.  *
  217.  * Side effects:
  218.  *    The major side effect of this routine is to invoke cache consistency
  219.  *    actions by other clients.  This also does conflict checking, like
  220.  *    preventing writing if a file is being executed.  Lastly, a shadow
  221.  *    stream is created here on the server to support migration.
  222.  *
  223.  *----------------------------------------------------------------------
  224.  */
  225. ReturnStatus
  226. Fsio_FileNameOpen(handlePtr, openArgsPtr, openResultsPtr)
  227.      register Fsio_FileIOHandle *handlePtr;    /* A handle from FslclLookup.
  228.                      * Should be LOCKED upon entry,
  229.                      * Returned UNLOCKED. */
  230.       Fs_OpenArgs        *openArgsPtr;    /* Standard open arguments */
  231.      Fs_OpenResults    *openResultsPtr;/* For returning ioFileID, streamID,
  232.                      * and Fsio_FileState */
  233. {
  234.     Fsio_FileState *fileStatePtr;
  235.     ReturnStatus status;
  236.     register useFlags = openArgsPtr->useFlags;
  237.     register clientID = openArgsPtr->clientID;
  238.     register Fs_Stream *streamPtr;
  239. #ifdef SOSP91
  240.     int realID = -1;
  241.     if (openResultsPtr->dataSize == sizeof(Fs_OpenArgsSOSP)) {
  242.     realID = ((Fs_OpenArgsSOSP *) openArgsPtr)->realID;
  243.     }
  244. #endif
  245.  
  246.     if ((useFlags & FS_WRITE) &&
  247.     (handlePtr->descPtr->fileType == FS_DIRECTORY)) {
  248.     status = FS_IS_DIRECTORY;
  249.     goto exit;
  250.     }
  251.     if (handlePtr->descPtr->fileType == FS_DIRECTORY) {
  252.     /*
  253.      * Strip off execute permission that was used to allow access to
  254.      * a directory.
  255.      */
  256.     useFlags &= ~FS_EXECUTE;
  257.     }
  258.     /*
  259.      * Check against writing and executing at the same time.  Fs_Open already
  260.      * checks that useFlags doesn't contain both execute and write bits.
  261.      */
  262.     if (((useFlags & FS_EXECUTE) && (handlePtr->use.write > 0)) ||
  263.     ((useFlags & (FS_WRITE|FS_CREATE)) && (handlePtr->use.exec > 0))) {
  264.     status = FS_FILE_BUSY;
  265.     goto exit;
  266.     }
  267.     /*
  268.      * Add in read permission when executing a file so Fs_Read doesn't
  269.      * foil page-ins later.
  270.      */
  271.     if ((useFlags & FS_EXECUTE) && (handlePtr->descPtr->fileType == FS_FILE)) {
  272.     useFlags |= FS_READ;
  273.     }
  274.     /*
  275.      * Set up the ioFileIDPtr so our caller can set/get attributes.
  276.      */
  277.     openResultsPtr->ioFileID = handlePtr->hdr.fileID;
  278.     if (clientID != rpc_SpriteID) {
  279.     openResultsPtr->ioFileID.type = FSIO_RMT_FILE_STREAM;
  280.     }
  281.     if (useFlags == 0) { 
  282.     /*
  283.      * Only being called from the get/set attributes code.
  284.      * Setting up the ioFileID is all that is needed.
  285.      */
  286.     status = SUCCESS;
  287.     } else {
  288.     /*
  289.      * Called during an open.  Update the summary use counts while
  290.      * we still have the handle locked.  Then unlock the handle and
  291.      * do consistency call-backs.  The handle is unlocked to allow
  292.      * servicing of RPCs which are side effects
  293.      * of the consistency requests (i.e. write-backs).
  294.      */
  295.     handlePtr->use.ref++;
  296.     if (useFlags & FS_WRITE) {
  297.         handlePtr->use.write++;
  298.         IncVersionNumber(handlePtr);
  299.     }
  300.     if (useFlags & FS_EXECUTE) {
  301.         handlePtr->use.exec++;
  302.     }
  303.     Fsutil_HandleUnlock(handlePtr);
  304.     fileStatePtr = mnew(Fsio_FileState);
  305.     status = Fsconsist_FileConsistency(handlePtr, clientID, useFlags,
  306.             &fileStatePtr->cacheable, &fileStatePtr->openTimeStamp);
  307.     if (status == SUCCESS) {
  308.         /*
  309.          * Copy cached attributes into the returned file state.
  310.          */
  311.         Fscache_GetCachedAttr(&handlePtr->cacheInfo, &fileStatePtr->version,
  312.             &fileStatePtr->attr);
  313.         /*
  314.          * Return new usage flags to the client.  This lets us strip
  315.          * off the execute use flag (above, for directories) so
  316.          * the client doesn't have to worry about it.
  317.          */
  318.         fileStatePtr->newUseFlags = useFlags;
  319.         openResultsPtr->streamData = (ClientData)fileStatePtr;
  320.         openResultsPtr->dataSize = sizeof(Fsio_FileState);
  321. #ifdef SOSP91
  322.     if (handlePtr->descPtr->fileType == FS_DIRECTORY) {
  323.         fileStatePtr->newUseFlags |= FS_DIR;
  324.     }
  325. #endif SOSP91
  326.  
  327.         /*
  328.          * Now set up a shadow stream on here on the server so we
  329.          * can support shared offset even after migration.
  330.          * Note: prefix handles get opened, but the stream is not used,
  331.          * could dispose stream in FslclExport.
  332.          */
  333.  
  334.         streamPtr = Fsio_StreamCreate(rpc_SpriteID, clientID,
  335.         (Fs_HandleHeader *)handlePtr, useFlags, handlePtr->hdr.name);
  336.         openResultsPtr->streamID = streamPtr->hdr.fileID;
  337.  
  338. #ifdef SOSP91
  339.         {
  340.         int numWriters;
  341.         int numReaders;
  342.         (void) Fsconsist_NumClients(&handlePtr->consist, 
  343.             &numReaders, &numWriters);
  344.         SOSP_ADD_OPEN_TRACE(openArgsPtr->clientID, 
  345.             openArgsPtr->migClientID, openResultsPtr->ioFileID,
  346.             openResultsPtr->streamID, openArgsPtr->id.user,
  347.             realID, openArgsPtr->useFlags, numReaders, numWriters,
  348.             fileStatePtr->attr.createTime,
  349.             fileStatePtr->attr.lastByte + 1,
  350.             fileStatePtr->attr.modifyTime,
  351.             handlePtr->descPtr->fileType, fileStatePtr->cacheable);
  352.         }
  353. #endif
  354.  
  355.         Fsutil_HandleRelease(streamPtr, TRUE);
  356.         return(SUCCESS);
  357.     } else {
  358.         /*
  359.          * Consistency call-backs failed because the last writer
  360.          * could not write back its copy of the file. We garbage
  361.          * collect the client to retreat to a known bookkeeping point.
  362.          */
  363.         int ref, write, exec;
  364.         printf("Consistency failed %x on <%d,%d>\n", status,
  365.         handlePtr->hdr.fileID.major, handlePtr->hdr.fileID.minor);
  366.         Fsutil_HandleLock(handlePtr);
  367.         Fsconsist_Kill(&handlePtr->consist, clientID,
  368.               &ref, &write, &exec);
  369.         handlePtr->use.ref   -= ref;
  370.         handlePtr->use.write -= write;
  371.         handlePtr->use.exec  -= exec;
  372.         if ((handlePtr->use.ref < 0) || (handlePtr->use.write < 0) ||
  373.             (handlePtr->use.exec < 0)) {
  374.         panic("Fsio_FileNameOpen: client %d ref %d write %d exec %d\n",
  375.             clientID, handlePtr->use.ref,
  376.             handlePtr->use.write, handlePtr->use.exec);
  377.         }
  378.         free((Address)fileStatePtr);
  379.     }
  380.     }
  381. exit:
  382.     Fsutil_HandleUnlock(handlePtr);
  383.     return(status);
  384. }
  385.  
  386. /*
  387.  *----------------------------------------------------------------------
  388.  *
  389.  * Fsio_FileReopen --
  390.  *
  391.  *      Reopen a file for use by a remote client. State is maintained in the
  392.  *      handle's client list about this open and whether or not the client
  393.  *      is caching.
  394.  *
  395.  * Results:
  396.  *    A failure code if the client was caching dirty blocks but lost
  397.  *    the race to re-open its file.  (i.e. another client already opened
  398.  *    for writing.)
  399.  *
  400.  * Side effects:
  401.  *    The client use state for the client is brought into agreement
  402.  *    with what the client tells us.  We do cache consistency too.
  403.  *    
  404.  *
  405.  *----------------------------------------------------------------------
  406.  */
  407. /*ARGSUSED*/
  408. ReturnStatus
  409. Fsio_FileReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  410.     Fs_HandleHeader    *hdrPtr;    /* IGNORED here on the server */
  411.     int            clientID;    /* Client doing the reopen */
  412.     ClientData        inData;        /* Fsio_FileReopenParams */
  413.     int            *outSizePtr;    /* Size of returned data */
  414.     ClientData        *outDataPtr;    /* Returned data */
  415. {
  416.     register Fsio_FileReopenParams *reopenParamsPtr; /* Parameters from RPC */
  417.     register Fsio_FileState    *fileStatePtr;    /* Results for RPC */
  418.     Fsio_FileIOHandle            *handlePtr;    /* Local handle for file */
  419.     register ReturnStatus    status = SUCCESS; /* General return code */
  420.     Fsdm_Domain            *domainPtr;
  421.  
  422.     *outDataPtr = (ClientData) NIL;
  423.     *outSizePtr = 0;
  424.     /*
  425.      * Do initial setup for the reopen.  We make sure that the disk
  426.      * for the file is still around first, mark the client
  427.      * as doing recovery, and fetch a local handle for the file.
  428.      * NAME note: we have no name for the file after a re-open.
  429.      */
  430.     reopenParamsPtr = (Fsio_FileReopenParams *) inData;
  431.     domainPtr = Fsdm_DomainFetch(reopenParamsPtr->fileID.major, FALSE);
  432.     if (domainPtr == (Fsdm_Domain *)NIL) {
  433.     return(FS_DOMAIN_UNAVAILABLE);
  434.     }
  435.     status = Fsio_LocalFileHandleInit(&reopenParamsPtr->fileID, (char *)NIL,
  436.     (Fsdm_FileDescriptor *) NIL, FALSE, &handlePtr);
  437.     if (status != SUCCESS) {
  438.     goto reopenReturn;
  439.     }
  440.     /*
  441.      * See if the client can still cache its dirty blocks.
  442.      */
  443.     if (reopenParamsPtr->flags & FSIO_HAVE_BLOCKS) {
  444.     status = Fscache_CheckVersion(&handlePtr->cacheInfo,
  445.                      reopenParamsPtr->version, clientID);
  446.     if (status != SUCCESS) {
  447.         Fsutil_HandleRelease(handlePtr, TRUE);
  448.         goto reopenReturn;
  449.     }
  450.     }
  451.     /*
  452.      * Update global use counts and version number.
  453.      */
  454.     Fsconsist_ReopenClient(handlePtr, clientID, reopenParamsPtr->use,
  455.             reopenParamsPtr->flags & FSIO_HAVE_BLOCKS);
  456.     if (reopenParamsPtr->use.write > 0) {
  457.     IncVersionNumber(handlePtr);
  458.     }
  459.     /*
  460.      * Now unlock the handle and do cache consistency call-backs.
  461.      */
  462.     fileStatePtr = mnew(Fsio_FileState);
  463.     fileStatePtr->cacheable = reopenParamsPtr->flags & FSIO_HAVE_BLOCKS;
  464.     Fsutil_HandleUnlock(handlePtr);
  465.     status = Fsconsist_ReopenConsistency(handlePtr, clientID, reopenParamsPtr->use,
  466.         reopenParamsPtr->flags & FS_SWAP,
  467.         &fileStatePtr->cacheable, &fileStatePtr->openTimeStamp);
  468.     if (status != SUCCESS) {
  469.     /*
  470.      * Consistency call-backs failed, probably due to disk-full.
  471.      * We kill the client here as it will invalidate its handle
  472.      * after this re-open fails.
  473.      */
  474.     int ref, write, exec;
  475.     Fsutil_HandleLock(handlePtr);
  476.     Fsconsist_Kill(&handlePtr->consist, clientID, &ref, &write, &exec);
  477.     handlePtr->use.ref   -= ref;
  478.     handlePtr->use.write -= write;
  479.     handlePtr->use.exec  -= exec;
  480.     if ((handlePtr->use.ref < 0) || (handlePtr->use.write < 0) ||
  481.         (handlePtr->use.exec < 0)) {
  482.         panic("Fsio_FileReopen: client %d ref %d write %d exec %d\n",
  483.         clientID, handlePtr->use.ref,
  484.         handlePtr->use.write, handlePtr->use.exec);
  485.     }
  486.     Fsutil_HandleUnlock(handlePtr);
  487.     free((Address)fileStatePtr);
  488.     } else {
  489.     /*
  490.      * Successful re-open here on the server. Copy cached attributes
  491.      * into the returned file state.
  492.      */
  493.     Fscache_GetCachedAttr(&handlePtr->cacheInfo, &fileStatePtr->version,
  494.             &fileStatePtr->attr);
  495.     fileStatePtr->newUseFlags = 0;        /* Not used in re-open */
  496.     *outDataPtr = (ClientData) fileStatePtr;
  497.     *outSizePtr = sizeof(Fsio_FileState);
  498.     }
  499.     Fsutil_HandleRelease(handlePtr, FALSE);
  500. reopenReturn:
  501.     Fsdm_DomainRelease(reopenParamsPtr->fileID.major);
  502.     return(status);
  503. }
  504.  
  505. /*
  506.  *----------------------------------------------------------------------
  507.  *
  508.  * Fsio_FileIoOpen --
  509.  *
  510.  *      Set up a stream for a local disk file.  This is called from Fs_Open to
  511.  *    complete the opening of a stream.  By this time any cache consistency
  512.  *    actions have already been taken, and local use counts have been
  513.  *    incremented by Fsio_FileNameOpen.
  514.  *
  515.  * Results:
  516.  *    SUCCESS, unless there was an error installing the handle.
  517.  *
  518.  * Side effects:
  519.  *    Installs the handle for the file.  This increments its refererence
  520.  *    count (different than the use count).
  521.  *
  522.  *----------------------------------------------------------------------
  523.  */
  524. /*ARGSUSED*/
  525. ReturnStatus
  526. Fsio_FileIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name, ioHandlePtrPtr)
  527.     Fs_FileID        *ioFileIDPtr;    /* I/O fileID from the name server */
  528.     int            *flagsPtr;    /* Return only.  The server returns
  529.                      * a modified useFlags in Fsio_FileState */
  530.     int            clientID;    /* IGNORED */
  531.     ClientData        streamData;    /* Fsio_FileState. */
  532.     char        *name;        /* File name for error msgs */
  533.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a handle set up for
  534.                      * I/O to a file, NIL if failure. */
  535. {
  536.     register ReturnStatus    status;
  537.  
  538.     status = Fsio_LocalFileHandleInit(ioFileIDPtr, name, 
  539.         (Fsdm_FileDescriptor *) NIL, FALSE, 
  540.         (Fsio_FileIOHandle **)ioHandlePtrPtr);
  541.     if (status == SUCCESS) {
  542.     /*
  543.      * Return the new useFlags from the server.  It has stripped off
  544.      * execute permission for directories.
  545.      */
  546.     *flagsPtr = ( (Fsio_FileState *)streamData )->newUseFlags;
  547.     Fsutil_HandleUnlock(*ioHandlePtrPtr);
  548.     }
  549.     free((Address)streamData);
  550.     return(status);
  551. }
  552.  
  553. /*
  554.  *----------------------------------------------------------------------
  555.  *
  556.  * Fsio_FileClose --
  557.  *
  558.  *    Close time processing for local files.  We need to remove ourselves
  559.  *    from the list of clients of the file, decrement use counts, and
  560.  *    handle pending deletes.  This returns either with one reference
  561.  *    to the handle released, or with the handle removed entirely.
  562.  *
  563.  * Results:
  564.  *    SUCCESS, FS_FILE_REMOVED, or an error code from the disk operation
  565.  *    on the file descriptor.
  566.  *
  567.  * Side effects:
  568.  *    Attributes cached on clients are propogated to the local handle.
  569.  *    Use counts in the client list are decremented.  The handle's
  570.  *    use counts are decremented.  If the file has been deleted, then
  571.  *    the file descriptor is so marked, other clients are told of
  572.  *    the delete, and the handle is removed entirely.  Otherwise,
  573.  *    a reference on the handle is released.
  574.  *
  575.  *----------------------------------------------------------------------
  576.  */
  577.  
  578. #ifndef SOSP91
  579. ReturnStatus
  580. Fsio_FileClose(streamPtr, clientID, procID, flags, dataSize, closeData)
  581. #else
  582. ReturnStatus
  583. Fsio_FileClose(streamPtr, clientID, procID, flags, dataSize, closeData,
  584.     offsetPtr, rwFlagsPtr)
  585. #endif
  586.     Fs_Stream        *streamPtr;    /* Stream to regular file */
  587.     int            clientID;    /* Host ID of closer */
  588.     Proc_PID        procID;        /* Process ID of closer */
  589.     int            flags;        /* Flags from the stream being closed */
  590.     int            dataSize;    /* Size of closeData */
  591.     ClientData        closeData;    /* Ref. to Fscache_Attributes */
  592. #ifdef SOSP91
  593.     int            *offsetPtr;
  594.     int            *rwFlagsPtr;
  595. #endif
  596. {
  597.     register Fsio_FileIOHandle *handlePtr =
  598.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  599.     ReturnStatus        status;
  600.     Boolean            wasCached = TRUE;
  601. #ifdef SOSP91
  602.     Boolean            didCloseConsist;
  603. #endif /* SOSP91 */
  604.  
  605.     /*
  606.      * Update the client state to reflect the close by the client.
  607.      */
  608.  
  609.     /*
  610.      * This code is to track down a problem with clients sending bad
  611.      * data.
  612.      */
  613.     if (flags & FS_EXECUTE) {
  614.     List_Links *clientList = &(handlePtr->consist.clientList);
  615.     Fsconsist_ClientInfo *clientPtr;
  616.     LIST_FORALL(clientList, (List_Links *)clientPtr) {
  617.         if (clientPtr->clientID == clientID) {
  618.            if (clientPtr->use.exec==0) {
  619.            printf("***ERROR***:Client %d: bad close on %s\n",
  620.                clientID, Fsutil_HandleName(handlePtr));
  621.           return(FAILURE);
  622.            }
  623.         }
  624.         }
  625.     }
  626.  
  627. #ifdef SOSP91
  628.     didCloseConsist = Fsconsist_Close(&handlePtr->consist, clientID, flags,
  629.         &wasCached);
  630.     if (!didCloseConsist) {
  631. #else /* SOSP91 */
  632.     if (!Fsconsist_Close(&handlePtr->consist, clientID, flags, &wasCached)) {
  633. #endif /* SOSP91 */
  634.     printf("Fsio_FileClose, client %d pid %x unknown for file <%d,%d>\n",
  635.           clientID, procID, handlePtr->hdr.fileID.major,
  636.           handlePtr->hdr.fileID.minor);
  637.     Fsutil_HandleUnlock(handlePtr);
  638.     return(FS_STALE_HANDLE);
  639.     }
  640.     if (wasCached && dataSize != 0) {
  641.     /*
  642.      * Update the server's attributes from ones cached on the client.
  643.      */
  644.     Fscache_UpdateAttrFromClient(clientID, &handlePtr->cacheInfo,
  645.                 (Fscache_Attributes *)closeData);
  646.     (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr, -1);
  647.     }
  648.  
  649.     Fsio_LockClose(&handlePtr->lock, &streamPtr->hdr.fileID);
  650.  
  651.     /*
  652.      * Update use counts and handle pending deletions.
  653.      */
  654.     status = Fsio_FileCloseInt(handlePtr, 1, (flags & FS_WRITE) != 0,
  655.                      (flags & FS_EXECUTE) != 0,
  656.                      clientID, TRUE);
  657. #ifdef SOSP91
  658.     {
  659.     int offset;
  660.     int rwFlags;
  661.     if ((offsetPtr != (int *) NIL) && !(streamPtr->flags & FS_RMT_SHARED)) {
  662.         offset = *offsetPtr;
  663.         rwFlags = *rwFlagsPtr;
  664.     } else {
  665.         offset = streamPtr->offset;
  666.         rwFlags = (streamPtr->hdr.flags & FSUTIL_RW_FLAGS) >> 8;
  667.     }
  668.     SOSP_ADD_CLOSE_TRACE(streamPtr->hdr.fileID, offset, 
  669.         handlePtr->cacheInfo.attr.lastByte + 1, streamPtr->flags,
  670.         rwFlags, handlePtr->use.ref, didCloseConsist);
  671.     }
  672. #endif
  673.     if (status == FS_FILE_REMOVED) {
  674.     if (clientID == rpc_SpriteID) {
  675.         status = SUCCESS;
  676.     }
  677.     } else {
  678.     status = SUCCESS;
  679.     Fsutil_HandleRelease(handlePtr, TRUE);
  680.     }
  681.  
  682.     return(status);
  683. }
  684.  
  685. /*
  686.  * ----------------------------------------------------------------------------
  687.  *
  688.  * Fsio_FileCloseInt --
  689.  *
  690.  *    Close a file, handling pending deletions.
  691.  *    This is called from the regular close routine, from
  692.  *    the file client-kill cleanup routine, and from the
  693.  *    lookup routine that deletes file names.
  694.  *
  695.  * Results:
  696.  *    SUCCESS or FS_FILE_REMOVED.
  697.  *
  698.  * Side effects:
  699.  *    Adjusts use counts and does pending deletions.  If the file is
  700.  *    deleted the handle can not be used anymore.  Otherwise it
  701.  *    is left locked.
  702.  *
  703.  * ----------------------------------------------------------------------------
  704.  *
  705.  */
  706. ReturnStatus
  707. Fsio_FileCloseInt(handlePtr, ref, write, exec, clientID, callback)
  708.     Fsio_FileIOHandle *handlePtr;    /* File to clean up */
  709.     int ref;                /* Number of uses to remove */
  710.     int write;                /* Number of writers to remove */
  711.     int exec;                /* Number of executers to remove */
  712.     int clientID;            /* Closing, or crashed, client */
  713.     Boolean callback;            /* TRUE if we should call back to
  714.                      * the client and tell it about
  715.                      * the deletion. */
  716. {
  717.     register ReturnStatus status;
  718.     /*
  719.      * Update the global/summary use counts for the file.
  720.      */
  721.     handlePtr->use.ref -= ref;
  722.     handlePtr->use.write -= write;
  723.     handlePtr->use.exec -= exec;
  724.     if (handlePtr->use.ref < 0 || handlePtr->use.write < 0 ||
  725.     handlePtr->use.exec < 0) {
  726.     panic("Fsio_FileCloseInt <%d,%d> use %d, write %d, exec %d\n",
  727.         handlePtr->hdr.fileID.major, handlePtr->hdr.fileID.minor,
  728.         handlePtr->use.ref, handlePtr->use.write, handlePtr->use.exec);
  729.     }
  730.  
  731.     /*
  732.      * Handle pending deletes
  733.      *    0. Make sure it isn't being deleted already.
  734.      *    1. Scan the client list and call-back to the last writer if
  735.      *        it is not the client doing the close.  The handle gets
  736.      *        temporarily unlocked during the callback, so we are
  737.      *        are careful to ensure only one process does the delete.
  738.      *    2. Mark the disk descriptor as deleted,
  739.      *    3. Remove the file handle.
  740.      *    4. Return FS_FILE_REMOVED so clients know to nuke their cache.
  741.      */
  742.     if ((handlePtr->use.ref == 0) &&
  743.     (handlePtr->flags & FSIO_FILE_NAME_DELETED)) {
  744.     if ((handlePtr->flags & FSIO_FILE_DESC_DELETED) == 0) {
  745.         handlePtr->flags |= FSIO_FILE_DESC_DELETED;
  746.         if (handlePtr->descPtr->fileType == FS_DIRECTORY) {
  747.         fs_Stats.object.directory--;
  748.         } else {
  749.         fs_Stats.object.files--;
  750.         }
  751.         if (callback) {
  752.         Fsconsist_ClientRemoveCallback(&handlePtr->consist, clientID);
  753.         }
  754. #ifdef SOSP91
  755.         SOSP_ADD_DELETE_DESC_TRACE(handlePtr->hdr.fileID,
  756.             handlePtr->cacheInfo.attr.modifyTime,
  757.             handlePtr->cacheInfo.attr.createTime,
  758.             handlePtr->cacheInfo.attr.lastByte + 1);
  759. #endif
  760.  
  761.         (void)Fslcl_DeleteFileDesc(handlePtr);
  762.         Fsio_FileSyncLockCleanup(handlePtr);
  763.         if (callback) {
  764.         Fsutil_HandleRelease(handlePtr, FALSE);
  765.         }
  766.         Fsutil_HandleRemove(handlePtr);
  767.     } else {
  768.         /*
  769.          * The following printf is a mousetrap to verify that the 
  770.          * bug where Proc_ServerProcs leave files locked was fixed.
  771.          * Remove it once we are positive the bug is fixed. JHH 11/5/90
  772.          */
  773.         printf(
  774.     "Fsio_FileCloseInt: almost returned FS_FILE_REMOVED w/ handle locked\n");
  775.         Fsutil_HandleUnlock(handlePtr);
  776.     }
  777.     status = FS_FILE_REMOVED;
  778.     } else {
  779.     status = SUCCESS;
  780.     }
  781.     return(status);
  782. }
  783.  
  784. /*
  785.  * ----------------------------------------------------------------------------
  786.  *
  787.  * Fsio_FileClientKill --
  788.  *
  789.  *    Called when a client is assumed down.  This cleans up the
  790.  *    cache consistency state associated with the client, and reflects
  791.  *    these changes in uses (i.e. less writers) in the handle's global
  792.  *    use counts.
  793.  *    
  794.  *
  795.  * Results:
  796.  *    SUCCESS.
  797.  *
  798.  * Side effects:
  799.  *    Removes the client list entry for the client and adjusts the
  800.  *    use counts on the file.  This has to remove or unlock the handle.
  801.  *
  802.  * ----------------------------------------------------------------------------
  803.  *
  804.  */
  805. void
  806. Fsio_FileClientKill(hdrPtr, clientID)
  807.     Fs_HandleHeader    *hdrPtr;    /* File to clean up */
  808.     int            clientID;    /* Host assumed down */
  809. {
  810.     Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
  811.     int refs, writes, execs;
  812.     register ReturnStatus status;
  813.  
  814.     Fsconsist_IOClientKill(&handlePtr->consist.clientList, clientID,
  815.             &refs, &writes, &execs);
  816.     Fsio_LockClientKill(&handlePtr->lock, clientID);
  817.  
  818.     status = Fsio_FileCloseInt(handlePtr, refs, writes, execs, clientID, FALSE);
  819.     if (status != FS_FILE_REMOVED) {
  820.     Fsutil_HandleUnlock(handlePtr);
  821.     }
  822. }
  823.  
  824. /*
  825.  * ----------------------------------------------------------------------------
  826.  *
  827.  * Fsio_FileScavenge --
  828.  *
  829.  *    Called periodically to see if this handle is still needed.
  830.  *    
  831.  *
  832.  * Results:
  833.  *    TRUE if it removed the handle.
  834.  *
  835.  * Side effects:
  836.  *    Removes the handle if their are no references to it and no
  837.  *    blocks in the cache for it.  Otherwise it unlocks the handle
  838.  *    before returning.
  839.  *
  840.  * ----------------------------------------------------------------------------
  841.  *
  842.  */
  843. /*ARGSUSED*/
  844. Boolean
  845. Fsio_FileScavenge(hdrPtr)
  846.     Fs_HandleHeader    *hdrPtr;    /* File to clean up */
  847. {
  848.     register Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
  849.     register Boolean noUsers;
  850.  
  851.     /*
  852.      * We can reclaim the handle if the following holds.
  853.      *  0. The descriptor is not dirty.
  854.      *    1. There are no active users of the file.
  855.      *  2. The file is not undergoing deletion
  856.      *        (The deletion will remove the handle soon)
  857.      *  3. There are no remote clients of the file.  In particular,
  858.      *        the last writer might not be active, but we can't
  859.      *        nuke the handle until after it writes back.
  860.      */
  861.     noUsers = ((handlePtr->descPtr->flags & FSDM_FD_DIRTY) == 0) &&
  862.                (handlePtr->use.ref == 0) &&
  863.          ((handlePtr->flags & (FSIO_FILE_DESC_DELETED|
  864.                    FSIO_FILE_NAME_DELETED)) == 0) &&
  865. #ifdef SOSP91
  866.           (Fsconsist_NumClients(&handlePtr->consist, (int *) NIL,
  867.           (int *) NIL) == 0);
  868. #else
  869.           (Fsconsist_NumClients(&handlePtr->consist) == 0);
  870. #endif
  871.     if (noUsers && Fscache_OkToScavenge(&handlePtr->cacheInfo)) {
  872.     register Boolean isDir;
  873. #ifdef CONSIST_DEBUG
  874.     extern int fsTraceConsistMinor;
  875.     if (fsTraceConsistMinor == handlePtr->hdr.fileID.minor) {
  876.         printf("Fsio_FileScavenge <%d,%d> nuked, lastwriter %d\n",
  877.         handlePtr->hdr.fileID.major, handlePtr->hdr.fileID.minor,
  878.         handlePtr->consist.lastWriter);
  879.     }
  880. #endif    CONSIST_DEBUG
  881.     /*
  882.      * Remove handles for files with no users and no blocks in cache.
  883.      * We tell VM not to cache the segment associated with the file.
  884.      * The "attempt remove" call unlocks the handle and then frees its
  885.      * memory if there are no references to it lingering from the name
  886.      * hash table.
  887.      */
  888.     Vm_FileChanged(&handlePtr->segPtr);
  889.     isDir = (handlePtr->descPtr->fileType == FS_DIRECTORY);
  890.     if (Fsutil_HandleAttemptRemove(hdrPtr)) {
  891.         if (isDir) {
  892.         fs_Stats.object.directory--;
  893.         fs_Stats.object.dirFlushed++;
  894.         } else {
  895.         fs_Stats.object.files--;
  896.         }
  897.         return(TRUE);
  898.     } else {
  899.         return(FALSE);
  900.     }
  901.     } else {
  902.     Fsutil_HandleUnlock(hdrPtr);
  903.     return(FALSE);
  904.     }
  905. }
  906.  
  907. /*
  908.  * ----------------------------------------------------------------------------
  909.  *
  910.  * Fsio_FileMigClose --
  911.  *
  912.  *    Initiate migration of a FSIO_LCL_FILE_STREAM.  There is no extra
  913.  *    state needed than already put together by Fsio_EncapStream.  However,
  914.  *    we do release a low-level reference on the handle which is
  915.  *    re-obtained by FsFileDeencap.  Other than that, we leave the
  916.  *    book-keeping alone, waiting to atomically switch references from
  917.  *    one client to the other at de-encapsulation time.
  918.  *    
  919.  *
  920.  * Results:
  921.  *    SUCCESS.
  922.  *
  923.  * Side effects:
  924.  *    Release a reference on the handle header.
  925.  *
  926.  * ----------------------------------------------------------------------------
  927.  *
  928.  */
  929. /*ARGSUSED*/
  930. ReturnStatus
  931. Fsio_FileMigClose(hdrPtr, flags)
  932.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  933.     int flags;            /* Use flags from the stream */
  934. {
  935.     panic( "Fsio_FileMigClose called\n");
  936.     Fsutil_HandleRelease(hdrPtr, FALSE);
  937.     return(SUCCESS);
  938. }
  939.  
  940.  
  941. /*
  942.  * ----------------------------------------------------------------------------
  943.  *
  944.  * Fsio_FileMigOpen --
  945.  *
  946.  *    Complete setup of a stream to a local file after migration to the
  947.  *    file server.  Fsio_FileMigrate has done the work of shifting use
  948.  *    counts at the stream and I/O handle level.  This routine has to
  949.  *    increment the low level I/O handle reference count to reflect
  950.  *    the existence of a new stream to the I/O handle.
  951.  *
  952.  * Results:
  953.  *    SUCCESS or FS_FILE_NOT_FOUND if the I/O handle can't be set up.
  954.  *
  955.  * Side effects:
  956.  *    Gains one reference to the I/O handle.  Frees the client data.
  957.  *
  958.  * ----------------------------------------------------------------------------
  959.  *
  960.  */
  961. /*ARGSUSED*/
  962. ReturnStatus
  963. Fsio_FileMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  964.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  965.     int        size;        /* sizeof(Fsio_FileState), IGNORED */
  966.     ClientData    data;        /* referenced to Fsio_FileState */
  967.     Fs_HandleHeader **hdrPtrPtr;    /* Return - I/O handle for the file */
  968. {
  969.     register ReturnStatus status;
  970.     register Fsio_FileIOHandle *handlePtr;
  971.  
  972.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle,
  973.         &migInfoPtr->ioFileID);
  974.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  975.     printf("Fsio_FileMigOpen, file <%d,%d> from client %d not found\n",
  976.         migInfoPtr->ioFileID.major, migInfoPtr->ioFileID.minor,
  977.         migInfoPtr->srcClientID);
  978.     status = FS_FILE_NOT_FOUND;
  979.     } else {
  980.     Fsutil_HandleUnlock(handlePtr);
  981.     *hdrPtrPtr = (Fs_HandleHeader *)handlePtr;
  982.     status = SUCCESS;
  983.     }
  984.     free((Address)data);
  985.     return(status);
  986. }
  987.  
  988. /*
  989.  * ----------------------------------------------------------------------------
  990.  *
  991.  * Fsio_FileMigrate --
  992.  *
  993.  *    This takes care of transfering references from one client to the other.
  994.  *    Three things are done:  cache consistency actions are taken to
  995.  *    reflect the movement of the client, file state is set up for use
  996.  *    on the client in the MigEnd procedure, and cross-network stream
  997.  *    sharing is detected.  A useful side-effect of this routine is
  998.  *    to properly set the type in the ioFileID, either FSIO_LCL_FILE_STREAM
  999.  *    or FSIO_RMT_FILE_STREAM.  In the latter case FsrmtFileMigrate
  1000.  *    is called to do all the work.
  1001.  *
  1002.  * Results:
  1003.  *    An error status if the I/O handle can't be set-up or if there
  1004.  *    is a cache consistency failure.  Otherwise SUCCESS is returned,
  1005.  *    *flagsPtr may have the FS_RMT_SHARED bit set, and *sizePtr
  1006.  *    and *dataPtr are set to reference Fsio_FileState.
  1007.  *
  1008.  * Side effects:
  1009.  *    Sets the correct stream type on the ioFileID.
  1010.  *    Shifts client references from the srcClient to the destClient.
  1011.  *    Set up and return Fsio_FileState for use by the MigEnd routine.
  1012.  *
  1013.  * ----------------------------------------------------------------------------
  1014.  *
  1015.  */
  1016. /*ARGSUSED*/
  1017. ReturnStatus
  1018. Fsio_FileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  1019.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  1020.     int        dstClientID;    /* ID of target client */
  1021.     int        *flagsPtr;    /* In/Out Stream usage flags */
  1022.     int        *offsetPtr;    /* Return - correct stream offset */
  1023.     int        *sizePtr;    /* Return - sizeof(Fsio_FileState) */
  1024.     Address    *dataPtr;    /* Return - pointer to Fsio_FileState */
  1025. {
  1026.     register Fsio_FileIOHandle    *handlePtr;
  1027.     register Fsio_FileState        *fileStatePtr;
  1028.     register ReturnStatus        status;
  1029.     Boolean                closeSrcClient;
  1030.  
  1031.     if (migInfoPtr->ioFileID.serverID != rpc_SpriteID) {
  1032.     /*
  1033.      * The file was local, which is why we were called, but is now remote.
  1034.      */
  1035.     migInfoPtr->ioFileID.type = FSIO_RMT_FILE_STREAM;
  1036.     return(FsrmtFileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  1037.         sizePtr, dataPtr));
  1038.     }
  1039.     migInfoPtr->ioFileID.type = FSIO_LCL_FILE_STREAM;
  1040.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, &migInfoPtr->ioFileID);
  1041.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  1042.     panic("Fsio_FileMigrate, no I/O handle");
  1043.     status = FS_STALE_HANDLE;
  1044.     } else {
  1045.  
  1046.     /*
  1047.      * At the stream level, add the new client to the set of clients
  1048.      * for the stream, and check for any cross-network stream sharing.
  1049.      * We only close the orignial client if the stream is unshared,
  1050.      * i.e. there are no references left there.
  1051.      */
  1052.     Fsio_StreamMigClient(migInfoPtr, dstClientID,
  1053.         (Fs_HandleHeader *)handlePtr, &closeSrcClient);
  1054.  
  1055.     /*
  1056.      * Adjust use counts on the I/O handle to reflect any new sharing.
  1057.      */
  1058.     Fsio_MigrateUseCounts(migInfoPtr->flags, closeSrcClient,
  1059.                   &handlePtr->use);
  1060.  
  1061.     /*
  1062.      * Update the client list, and take any required cache consistency
  1063.      * actions. The handle returns unlocked from the consistency routine.
  1064.      */
  1065.     fileStatePtr = mnew(Fsio_FileState);
  1066.     Fsutil_HandleUnlock(handlePtr);
  1067.     status = Fsconsist_MigrateConsistency(handlePtr,
  1068.         migInfoPtr->srcClientID,
  1069.         dstClientID, migInfoPtr->flags, closeSrcClient,
  1070.         &fileStatePtr->cacheable, &fileStatePtr->openTimeStamp);
  1071.     if (status == SUCCESS) {
  1072.         Fscache_GetCachedAttr(&handlePtr->cacheInfo, &fileStatePtr->version,
  1073.                 &fileStatePtr->attr);
  1074.         *sizePtr = sizeof(Fsio_FileState);
  1075.         *dataPtr = (Address)fileStatePtr;
  1076.         *flagsPtr = fileStatePtr->newUseFlags = migInfoPtr->flags;
  1077.         *offsetPtr = migInfoPtr->offset;
  1078.     } else {
  1079.         free((Address)fileStatePtr);
  1080.     }
  1081.     /*
  1082.      * We don't need this reference on the I/O handle, there is no change.
  1083.      */
  1084.     Fsutil_HandleRelease(handlePtr, FALSE);
  1085.     }
  1086.     return(status);
  1087. }
  1088.  
  1089. /*
  1090.  *----------------------------------------------------------------------
  1091.  *
  1092.  * Fsio_FileRead --
  1093.  *
  1094.  *    Read from a file.  This is a thin layer on top of the cache
  1095.  *    read routine.
  1096.  *
  1097.  * Results:
  1098.  *    The results of Fscache_Read.
  1099.  *
  1100.  * Side effects:
  1101.  *    None, because Fscache_Read does most everything.
  1102.  *
  1103.  *----------------------------------------------------------------------
  1104.  */
  1105. ReturnStatus
  1106. Fsio_FileRead(streamPtr, readPtr, remoteWaitPtr, replyPtr)
  1107.     Fs_Stream        *streamPtr;    /* Open stream to the file. */
  1108.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  1109.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  1110.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  1111.                      * plus the amount read. */
  1112. {
  1113.     register Fsio_FileIOHandle *handlePtr =
  1114.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  1115.     register ReturnStatus status;
  1116.     int savedOffset = readPtr->offset;
  1117.     int savedLength = readPtr->length;
  1118. #ifdef SOSP91
  1119.     Fsconsist_Info *consistPtr = &handlePtr->consist;
  1120.     Fsconsist_ClientInfo    *clientPtr;
  1121.     Boolean            maybeShared = FALSE;
  1122.     int                numReading, numWriting;
  1123.  
  1124.     if ((handlePtr->descPtr != (Fsdm_FileDescriptor *) NIL) &&
  1125.         (handlePtr->descPtr->fileType == FS_FILE)) {
  1126.     /*
  1127.      * If this file is marked uncacheable or if we are the server doing
  1128.      * a read and it's marked uncacheable on another client, then record
  1129.      * this read.
  1130.      */
  1131.     LIST_FORALL(&consistPtr->clientList, (List_Links *) clientPtr) {
  1132.         if ((clientPtr->clientID == readPtr->reserved) &&
  1133.             (!clientPtr->cached)) {
  1134.         maybeShared = TRUE;
  1135.         break;
  1136.         } else if ((readPtr->reserved == rpc_SpriteID) &&
  1137.             (!clientPtr->cached)) {
  1138.         maybeShared = TRUE;
  1139.         break;
  1140.         }
  1141.     }
  1142.     }
  1143.     if (maybeShared) {
  1144.     (void) Fsconsist_NumClients(consistPtr, &numReading, &numWriting);
  1145.     SOSP_ADD_READ_TRACE(readPtr->reserved, 
  1146.         handlePtr->hdr.fileID, streamPtr->hdr.fileID, TRUE,
  1147.         readPtr->offset, readPtr->length, numReading, numWriting);
  1148.  
  1149.     }
  1150. #endif SOSP91
  1151.  
  1152.     status = Fscache_Read(&handlePtr->cacheInfo, readPtr->flags,
  1153.         readPtr->buffer, readPtr->offset, &readPtr->length, remoteWaitPtr);
  1154.     
  1155.     if ((status == SUCCESS) || (readPtr->length > 0)) { 
  1156.     (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr,
  1157.                 FSDM_FD_ACCESSTIME_DIRTY);
  1158.     if (readPtr->flags & FS_SWAP) {
  1159.         int hostID = Proc_GetHostID(readPtr->procID);
  1160.         if (hostID == rpc_SpriteID)  {
  1161.         /*
  1162.          * While page-ins on the file server come from its cache, we
  1163.          * inform the cache that these pages are good canidicates
  1164.          * for replacement.
  1165.          */
  1166.         Fscache_BlocksUnneeded(streamPtr, savedOffset, savedLength, 
  1167.                 FALSE);
  1168.         }
  1169.     }
  1170.  
  1171.     }
  1172.     replyPtr->length = readPtr->length;
  1173.     return(status);
  1174. }
  1175.  
  1176. /*
  1177.  *----------------------------------------------------------------------
  1178.  *
  1179.  * Fsio_FileWrite --
  1180.  *
  1181.  *    Write to a disk file.  This is a thin layer on top of the cache
  1182.  *    write routine.  Besides doing the write, this routine synchronizes
  1183.  *    with read ahead on the file.
  1184.  *
  1185.  * Results:
  1186.  *    The results of Fscache_Write.
  1187.  *
  1188.  * Side effects:
  1189.  *    The handle is locked during the I/O.
  1190.  *
  1191.  *----------------------------------------------------------------------
  1192.  */
  1193. ReturnStatus
  1194. Fsio_FileWrite(streamPtr, writePtr, remoteWaitPtr, replyPtr)
  1195.     Fs_Stream        *streamPtr;    /* Open stream to the file. */
  1196.     Fs_IOParam        *writePtr;    /* Read parameter block */
  1197.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  1198.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  1199. {
  1200.     register Fsio_FileIOHandle *handlePtr =
  1201.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  1202.     register ReturnStatus status;
  1203.     int savedOffset = writePtr->offset;
  1204.     int savedLength = writePtr->length;
  1205. #ifdef SOSP91
  1206.     Fsconsist_Info *consistPtr = &handlePtr->consist;
  1207.     Fsconsist_ClientInfo    *clientPtr;
  1208.     Boolean            maybeShared = FALSE;
  1209.     int                numReading, numWriting;
  1210.  
  1211.     if ((handlePtr->descPtr != (Fsdm_FileDescriptor *) NIL) &&
  1212.         (handlePtr->descPtr->fileType == FS_FILE)) {
  1213.     /*
  1214.      * If this file is marked uncacheable or if we are the server doing
  1215.      * a read and it's marked uncacheable on another client, then record
  1216.      * this read.
  1217.      */
  1218.     LIST_FORALL(&consistPtr->clientList, (List_Links *) clientPtr) {
  1219.         if ((clientPtr->clientID == writePtr->reserved) &&
  1220.             (!clientPtr->cached)) {
  1221.         maybeShared = TRUE;
  1222.         break;
  1223.         } else if ((writePtr->reserved == rpc_SpriteID) &&
  1224.             (!clientPtr->cached)) {
  1225.         maybeShared = TRUE;
  1226.         break;
  1227.         }
  1228.     }
  1229.     }
  1230.     if (maybeShared) {
  1231.     (void) Fsconsist_NumClients(consistPtr, &numReading, &numWriting);
  1232.     SOSP_ADD_READ_TRACE(writePtr->reserved, handlePtr->hdr.fileID,
  1233.         streamPtr->hdr.fileID, FALSE, writePtr->offset, 
  1234.         writePtr->length, numReading, numWriting);
  1235.     }
  1236.  
  1237. #endif SOSP91
  1238.  
  1239.     /*
  1240.      * Get a reference to the domain so it can't be dismounted during the I/O.
  1241.      * Then synchronize with read ahead before actually doing the write.
  1242.      */
  1243.     if (Fsdm_DomainFetch(handlePtr->hdr.fileID.major, FALSE) ==
  1244.         (Fsdm_Domain *)NIL) {
  1245.     return(FS_DOMAIN_UNAVAILABLE);
  1246.     }
  1247.     Fscache_WaitForReadAhead(&handlePtr->readAhead);
  1248.     status = Fscache_Write(&handlePtr->cacheInfo, writePtr->flags,
  1249.               writePtr->buffer, writePtr->offset,
  1250.               &writePtr->length, remoteWaitPtr);
  1251.     replyPtr->length = writePtr->length;
  1252.     if (status == SUCCESS) {
  1253.     if (replyPtr->length > 0) {
  1254.         (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr, 
  1255.             FSDM_FD_MODTIME_DIRTY);
  1256.     }
  1257.     if (writePtr->flags & FS_SWAP) {
  1258.         int hostID = Proc_GetHostID(writePtr->procID);
  1259.         if (hostID == rpc_SpriteID)  {
  1260.         /*
  1261.          * While page-outs on the file server go to its cache, we
  1262.          * inform the cache that these pages are good canidicates
  1263.          * for replacement.
  1264.          */
  1265.          Fscache_BlocksUnneeded(streamPtr, savedOffset, savedLength, 
  1266.                 FALSE);
  1267.         }
  1268.     }
  1269.     }
  1270.  
  1271.     Fscache_AllowReadAhead(&handlePtr->readAhead);
  1272.     Fsdm_DomainRelease(handlePtr->hdr.fileID.major);
  1273.     return(status);
  1274. }
  1275.  
  1276. /*
  1277.  *----------------------------------------------------------------------
  1278.  *
  1279.  * Fsio_FileBlockCopy --
  1280.  *
  1281.  *    Copy the block from the source swap file to the destination swap file.
  1282.  *
  1283.  *    NOTE: This routine does not call the routine that puts swap file blocks
  1284.  *          on the front of the free list.  This is because the general
  1285.  *          mode of doing things is to fork which copies the swap file and
  1286.  *          then exec which removes it.  Thus we want the swap file to be
  1287.  *          in the cache for the copy and we don't have to put the 
  1288.  *          destination files blocks on front of the lru list because it
  1289.  *          is going to get removed real soon anyway.
  1290.  *
  1291.  * Results:
  1292.  *    Error code if couldn't allocate disk space or didn't read a full
  1293.  *    block.
  1294.  *
  1295.  * Side effects:
  1296.  *    None.
  1297.  *
  1298.  *----------------------------------------------------------------------
  1299.  */
  1300. /*ARGSUSED*/
  1301. ReturnStatus
  1302. Fsio_FileBlockCopy(srcHdrPtr, dstHdrPtr, blockNum)
  1303.     Fs_HandleHeader    *srcHdrPtr;    /* File to copy block from.  */
  1304.     Fs_HandleHeader    *dstHdrPtr;    /* File to copy block to.  */
  1305.     int            blockNum;    /* Block to copy. */
  1306. {
  1307.     int            offset;
  1308.     ReturnStatus    status;
  1309.     Fscache_Block    *cacheBlockPtr;
  1310.     int            numBytes;
  1311.     register Fsio_FileIOHandle *srcHandlePtr =
  1312.         (Fsio_FileIOHandle *)srcHdrPtr;
  1313.     register Fsio_FileIOHandle *dstHandlePtr =
  1314.         (Fsio_FileIOHandle *)dstHdrPtr;
  1315.  
  1316.     /*
  1317.      * Look in the cache for the source block.
  1318.      */
  1319.     status = Fscache_BlockRead(&srcHandlePtr->cacheInfo, blockNum,
  1320.             &cacheBlockPtr, &numBytes, FSCACHE_DATA_BLOCK, FALSE);
  1321.     if (status != SUCCESS) {
  1322.     return(status);
  1323.     }
  1324.     if (numBytes != FS_BLOCK_SIZE) {
  1325.     if (numBytes != 0) {
  1326.         Fscache_UnlockBlock(cacheBlockPtr, 0, -1, 0,
  1327.             FSCACHE_CLEAR_READ_AHEAD);
  1328.     }
  1329.     return(VM_SHORT_READ);
  1330.     }
  1331.     /*
  1332.      * Write to the destination block.
  1333.      */
  1334.     numBytes = FS_BLOCK_SIZE;
  1335.     offset = blockNum * FS_BLOCK_SIZE;
  1336.     status = Fscache_Write(&dstHandlePtr->cacheInfo, FALSE,
  1337.             cacheBlockPtr->blockAddr, offset, &numBytes,
  1338.             (Sync_RemoteWaiter *) NIL);
  1339.     if (status == SUCCESS && numBytes != FS_BLOCK_SIZE) {
  1340.  
  1341.     status = VM_SHORT_WRITE;
  1342.     }
  1343.  
  1344.     Fscache_UnlockBlock(cacheBlockPtr, 0, -1, 0, FSCACHE_CLEAR_READ_AHEAD);
  1345.  
  1346.     srcHandlePtr->cacheInfo.attr.accessTime = Fsutil_TimeInSeconds();
  1347.     dstHandlePtr->cacheInfo.attr.modifyTime = Fsutil_TimeInSeconds();
  1348.     (void)Fsdm_UpdateDescAttr(srcHandlePtr, &srcHandlePtr->cacheInfo.attr, 
  1349.             FSDM_FD_ACCESSTIME_DIRTY);
  1350.     (void)Fsdm_UpdateDescAttr(dstHandlePtr, &dstHandlePtr->cacheInfo.attr, 
  1351.             FSDM_FD_MODTIME_DIRTY);
  1352.  
  1353.     return(status);
  1354. }
  1355.  
  1356. /*
  1357.  *----------------------------------------------------------------------
  1358.  *
  1359.  * Fsio_FileIOControl --
  1360.  *
  1361.  *    IOControls for regular files.  The handle should be locked up entry.
  1362.  *    This handles byte swapping of its input and output buffers if
  1363.  *    the clients byte ordering/padding is different.
  1364.  *
  1365.  * Results:
  1366.  *    An error code from the command.
  1367.  *
  1368.  * Side effects:
  1369.  *    Command dependent.
  1370.  *
  1371.  *----------------------------------------------------------------------
  1372.  */
  1373.  
  1374. /*ARGSUSED*/
  1375. ReturnStatus
  1376. Fsio_FileIOControl(streamPtr, ioctlPtr, replyPtr)
  1377.     Fs_Stream *streamPtr;        /* Stream to local file */
  1378.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  1379.     Fs_IOReply *replyPtr;        /* Return length and signal */
  1380. {
  1381.     register Fsio_FileIOHandle *handlePtr =
  1382.         (Fsio_FileIOHandle *)streamPtr->ioHandlePtr;
  1383.     register ReturnStatus status = SUCCESS;
  1384.     Boolean    unLock;
  1385.  
  1386.     Fsutil_HandleLock(handlePtr);
  1387.     unLock = TRUE;
  1388.     switch(ioctlPtr->command) {
  1389.     case IOC_REPOSITION:
  1390.         break;
  1391.     case IOC_GET_FLAGS:
  1392.         if ((ioctlPtr->outBufSize >= sizeof(int)) &&
  1393.         (ioctlPtr->outBuffer != (Address)NIL)) {
  1394.         *(int *)ioctlPtr->outBuffer = 0;
  1395.         }
  1396.         break;
  1397.     case IOC_SET_FLAGS:
  1398.     case IOC_SET_BITS:
  1399.     case IOC_CLEAR_BITS:
  1400.         break;
  1401. #ifdef 0
  1402.     case IOC_MAP:
  1403. #endif
  1404.     case IOC_TRUNCATE: {
  1405.         int arg;        /* The truncation length for IOC_TRUNCATE,
  1406.                  * The mapping flag for IOC_MAP. */
  1407.  
  1408.         if (ioctlPtr->inBufSize < sizeof(int)) {
  1409.         status = GEN_INVALID_ARG;
  1410.         } else if (ioctlPtr->format != mach_Format) {
  1411.         int outSize = sizeof(int);
  1412.         int inSize = sizeof(int);
  1413.         int fmtStatus;
  1414.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize, 
  1415.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1416.                 (Address) &arg);
  1417.         if (fmtStatus != 0) {
  1418.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1419.             status = GEN_INVALID_ARG;
  1420.         }
  1421.         if (outSize != sizeof(int)) {
  1422.             status = GEN_INVALID_ARG;
  1423.         }
  1424.         } else {
  1425.         arg = *(int *)ioctlPtr->inBuffer;
  1426.         }
  1427.         if (status == SUCCESS) {
  1428.         if (ioctlPtr->command == IOC_TRUNCATE) {
  1429.             if (arg < 0) {
  1430.             status = GEN_INVALID_ARG;
  1431.             } else {
  1432. #ifdef SOSP91
  1433.             {
  1434.                 int oldSize;
  1435.                 int modifyTime = 
  1436.                 handlePtr->cacheInfo.attr.modifyTime;
  1437.                 oldSize = handlePtr->cacheInfo.attr.lastByte;
  1438.                 status = Fsio_FileTrunc(handlePtr, arg, 0);
  1439.                 SOSP_ADD_TRUNCATE_TRACE(streamPtr->hdr.fileID,
  1440.                 oldSize + 1, 
  1441.                 handlePtr->cacheInfo.attr.lastByte + 1,
  1442.                 modifyTime,
  1443.                 handlePtr->cacheInfo.attr.createTime);
  1444.             }
  1445. #else
  1446.             status = Fsio_FileTrunc(handlePtr, arg, 0);
  1447. #endif
  1448.             }
  1449.         } else {
  1450.             Fsutil_HandleUnlock(handlePtr);
  1451.             unLock = FALSE;
  1452.             status = Fsconsist_MappedConsistency(handlePtr,
  1453.                 ioctlPtr->uid, arg);
  1454.         }
  1455.         }
  1456.         break;
  1457.     }
  1458.     case IOC_LOCK:
  1459.     case IOC_UNLOCK:
  1460.         status = Fsio_IocLock(&handlePtr->lock, ioctlPtr,
  1461.                 &streamPtr->hdr.fileID);
  1462.         break;
  1463.     case IOC_NUM_READABLE: {
  1464.         /*
  1465.          * Return the number of bytes available to read.  The top-level
  1466.          * IOControl routine has put the current stream offset in inBuffer.
  1467.          */
  1468.         int bytesAvailable;
  1469.         int streamOffset;
  1470.         int size;
  1471.  
  1472.         if (ioctlPtr->inBufSize != sizeof(int)) {
  1473.         status = GEN_INVALID_ARG;
  1474.         } else if (ioctlPtr->format != mach_Format) {
  1475.         int fmtStatus;
  1476.         int inSize;
  1477.         inSize = ioctlPtr->inBufSize;
  1478.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize, 
  1479.                 ioctlPtr->inBuffer, mach_Format, &size,
  1480.                 (Address) &streamOffset);
  1481.         if (fmtStatus != 0) {
  1482.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1483.             status = GEN_INVALID_ARG;
  1484.         }
  1485.         if (size != sizeof(int)) {
  1486.             status = GEN_INVALID_ARG;
  1487.         }
  1488.         } else {
  1489.         streamOffset = *(int *)ioctlPtr->inBuffer;
  1490.         }
  1491.         if (status == SUCCESS) {
  1492.         bytesAvailable = handlePtr->cacheInfo.attr.lastByte + 1 -
  1493.                 streamOffset;
  1494.         if (ioctlPtr->outBufSize != sizeof(int)) {
  1495.             status = GEN_INVALID_ARG;
  1496.         } else if (ioctlPtr->format != mach_Format) {
  1497.             int fmtStatus;
  1498.             int    inSize;
  1499.             inSize = sizeof(int);
  1500.             fmtStatus = Fmt_Convert("w", mach_Format, &inSize, 
  1501.                     (Address) &bytesAvailable, ioctlPtr->format,
  1502.                     &size, ioctlPtr->outBuffer);
  1503.             if (fmtStatus != 0) {
  1504.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1505.             status = GEN_INVALID_ARG;
  1506.             }
  1507.             if (size != sizeof(int)) {
  1508.             status = GEN_INVALID_ARG;
  1509.             }
  1510.         } else {
  1511.             *(int *)ioctlPtr->outBuffer = bytesAvailable;
  1512.         }
  1513.         }
  1514.         break;
  1515.     }
  1516.     case IOC_SET_OWNER:
  1517.     case IOC_GET_OWNER:
  1518.         status = GEN_NOT_IMPLEMENTED;
  1519.         break;
  1520.     case IOC_PREFIX:
  1521.         break;
  1522.     case IOC_WRITE_BACK: {
  1523.         /*
  1524.          * Write out the cached data for the file.
  1525.          */
  1526.         Ioc_WriteBackArgs *argPtr = (Ioc_WriteBackArgs *)ioctlPtr->inBuffer;
  1527.         Fscache_FileInfo *cacheInfoPtr = &handlePtr->cacheInfo;
  1528.  
  1529.         if (ioctlPtr->inBufSize < sizeof(Ioc_WriteBackArgs)) {
  1530.         status = GEN_INVALID_ARG;
  1531.         } else {
  1532.         int firstBlock, lastBlock;
  1533.         int blocksSkipped;
  1534.         int flags = 0;
  1535.         Ioc_WriteBackArgs writeBack;
  1536.  
  1537.         if (ioctlPtr->format != mach_Format) {
  1538.             int fmtStatus;
  1539.             int size;
  1540.             size = ioctlPtr->inBufSize;
  1541.             fmtStatus = Fmt_Convert("w3", ioctlPtr->format, &size, 
  1542.                     ioctlPtr->inBuffer, mach_Format, &size,
  1543.                     (Address) &writeBack);
  1544.             if (fmtStatus != 0) {
  1545.             printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  1546.             status = GEN_INVALID_ARG;
  1547.             }
  1548.             if (size != sizeof(Ioc_WriteBackArgs)) {
  1549.             status = GEN_INVALID_ARG;
  1550.             }
  1551.             if (status != SUCCESS) {
  1552.             break;
  1553.             }
  1554.             argPtr = &writeBack;
  1555.         }
  1556.         if (argPtr->shouldBlock) {
  1557.             flags |= FSCACHE_FILE_WB_WAIT;
  1558.         }
  1559.         if (argPtr->firstByte > 0) {
  1560.             firstBlock = argPtr->firstByte / FS_BLOCK_SIZE;
  1561.         } else {
  1562.             firstBlock = 0;
  1563.         }
  1564.         if (argPtr->lastByte > 0) {
  1565.             lastBlock = argPtr->lastByte / FS_BLOCK_SIZE;
  1566.         } else {
  1567.             lastBlock = FSCACHE_LAST_BLOCK;
  1568.         }
  1569. #ifdef SOSP91
  1570.         cacheInfoPtr->flags |= FSCACHE_SYNC;
  1571. #endif SOSP91
  1572.         /*
  1573.          * Release the handle lock during the FileWriteBack to 
  1574.          * avoid hanging up everyone who stumbles over the handle
  1575.          * during the writeback.
  1576.          */
  1577.         Fsutil_HandleUnlock(handlePtr);
  1578.         unLock = FALSE;
  1579.         status = Fscache_FileWriteBack(cacheInfoPtr, firstBlock,
  1580.             lastBlock, flags, &blocksSkipped);
  1581.         }
  1582.         break;
  1583.     }
  1584.     default:
  1585.         status = GEN_INVALID_ARG;
  1586.         break;
  1587.     }
  1588.     if (unLock) { 
  1589.     Fsutil_HandleUnlock(handlePtr);
  1590.     }
  1591.     return(status);
  1592. }
  1593.  
  1594. /*
  1595.  *----------------------------------------------------------------------
  1596.  *
  1597.  * Fsio_FileTrunc --
  1598.  *
  1599.  *    Shorten a file to length bytes.  This calls routines to update
  1600.  *    the cacheInfo and the fileDescriptor.
  1601.  *
  1602.  * Results:
  1603.  *    Error status from Fsdm_FileTrunc.
  1604.  *
  1605.  * Side effects:
  1606.  *    None.
  1607.  *
  1608.  *----------------------------------------------------------------------
  1609.  */
  1610.  
  1611. ReturnStatus
  1612. Fsio_FileTrunc(handlePtr, size, flags)
  1613.     Fsio_FileIOHandle    *handlePtr;    /* File to truncate. */
  1614.     int            size;        /* Size to truncate the file to. */
  1615.     int            flags;        /* FSCACHE_TRUNC_DELETE */
  1616. {
  1617.     ReturnStatus status;
  1618.  
  1619.     status = Fscache_Trunc(&handlePtr->cacheInfo, size, flags);
  1620.     if ((flags & FSCACHE_TRUNC_DELETE) == 0) {
  1621.     (void)Fsdm_UpdateDescAttr(handlePtr, &handlePtr->cacheInfo.attr, 
  1622.             FSDM_FD_MODTIME_DIRTY);
  1623.     }
  1624.     return(status);
  1625. }
  1626.  
  1627. /*
  1628.  *----------------------------------------------------------------------
  1629.  *
  1630.  * Fsio_FileSelect --
  1631.  *
  1632.  *    Always returns that file is readable and writable.
  1633.  *
  1634.  * Results:
  1635.  *    SUCCESS        - always returned.
  1636.  *
  1637.  * Side effects:
  1638.  *    None.
  1639.  *
  1640.  *----------------------------------------------------------------------
  1641.  */
  1642. /*ARGSUSED*/
  1643. ReturnStatus
  1644. Fsio_FileSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
  1645.     Fs_HandleHeader *hdrPtr;    /* The handle of the file */
  1646.     Sync_RemoteWaiter *waitPtr;    /* Process info for waiting */
  1647.     int        *readPtr;    /* Read bit */
  1648.     int        *writePtr;    /* Write bit */
  1649.     int        *exceptPtr;    /* Exception bit */
  1650. {
  1651.     *exceptPtr = 0;
  1652.     return(SUCCESS);
  1653. }
  1654.  
  1655. /*
  1656.  *----------------------------------------------------------------------------
  1657.  *
  1658.  * IncVersionNumber --
  1659.  *
  1660.  *    Increment the version number on file.  This is done when a file
  1661.  *    is opened for writing, and the version number is used by clients
  1662.  *    to verify their caches.  This must be called with the handle locked.
  1663.  *
  1664.  * Results:
  1665.  *    None.
  1666.  *
  1667.  * Side effects:
  1668.  *    Version number incremented and the descriptor is pushed to disk.
  1669.  *
  1670.  *----------------------------------------------------------------------------
  1671.  *
  1672.  */
  1673. void
  1674. IncVersionNumber(handlePtr)
  1675.     Fsio_FileIOHandle    *handlePtr;
  1676. {
  1677.     Fsdm_FileDescriptor    *descPtr;
  1678.  
  1679.     descPtr = handlePtr->descPtr;
  1680.     descPtr->version++;
  1681.     handlePtr->cacheInfo.version = descPtr->version;
  1682.     descPtr->flags |= FSDM_FD_VERSION_DIRTY;
  1683.     (void)Fsdm_FileDescStore(handlePtr, FALSE);
  1684.     Vm_FileChanged(&handlePtr->segPtr);
  1685. }
  1686.  
  1687.  
  1688. /*
  1689.  *----------------------------------------------------------------------
  1690.  *
  1691.  * Fsio_FileRecovTestUseCount --
  1692.  *
  1693.  *    For recovery testing, return the use count on the file's io handle.
  1694.  *
  1695.  * Results:
  1696.  *    Use count.
  1697.  *
  1698.  * Side effects:
  1699.  *    None.
  1700.  *
  1701.  *----------------------------------------------------------------------
  1702.  */
  1703. int
  1704. Fsio_FileRecovTestUseCount(handlePtr)
  1705.     Fsio_FileIOHandle    *handlePtr;
  1706. {
  1707.     return handlePtr->use.ref;
  1708. }
  1709.  
  1710.  
  1711. /*
  1712.  *----------------------------------------------------------------------
  1713.  *
  1714.  * Fsio_FileRecovTestNumCacheBlocks --
  1715.  *
  1716.  *    For recovery testing, return the number of blocks in the cache
  1717.  *    for this file.
  1718.  *
  1719.  * Results:
  1720.  *    Number of blocks.
  1721.  *
  1722.  * Side effects:
  1723.  *    None.
  1724.  *
  1725.  *----------------------------------------------------------------------
  1726.  */
  1727. int
  1728. Fsio_FileRecovTestNumCacheBlocks(handlePtr)
  1729.     Fsio_FileIOHandle    *handlePtr;
  1730. {
  1731.     return handlePtr->cacheInfo.blocksInCache;
  1732. }
  1733.  
  1734.  
  1735. /*
  1736.  *----------------------------------------------------------------------
  1737.  *
  1738.  * Fsio_FileRecovTestNumDirtyCacheBlocks --
  1739.  *
  1740.  *    For recovery testing, return the number of dirty blocks in the cache
  1741.  *    for this file.
  1742.  *
  1743.  * Results:
  1744.  *    Number of dirty blocks.
  1745.  *
  1746.  * Side effects:
  1747.  *    None.
  1748.  *
  1749.  *----------------------------------------------------------------------
  1750.  */
  1751. int
  1752. Fsio_FileRecovTestNumDirtyCacheBlocks(handlePtr)
  1753.     Fsio_FileIOHandle    *handlePtr;
  1754. {
  1755.     return handlePtr->cacheInfo.numDirtyBlocks;
  1756. }
  1757.